<template>
  <div 
    class="time-view">
    <div
      class="top"
      :class="[hasYItems ? 'hasYItems' : '']">
      

      <div v-scroll-sync.x class="x-axis">
        <!-- x轴元素生成 -->
        <div
          class="table-cell"
          :style="[cellStyle]"
          v-for="(x, xindex) in xItems"
          :key="xindex"
          >{{ x }}</div>
      </div>
    </div>

    <div
      class="main"
      :class="[hasControl ? 'has-foot' : '']">

      <div v-if="hasYItems" v-scroll-sync.y class="y-axis">
        <!-- y轴元素生成 -->
        <div
          class="table-cell y-item"
          :style="[cellStyle, {'line-height': `${yitemHeight}px`}]"
          v-for="(y, yindex) in yItems"
          :key="yindex"
          >{{ y }}</div>
      </div>


      <!-- 面板 -->
      <div
        v-scroll-sync.x
        v-scroll-sync.y
        ref="table"
        class="time-view-table"
        :class="[hasYItems ? 'hasYItems' : '']">
        <div
          v-for="(num) in rowsNum"
          :key="num"
          class="table-row"
          :style="[rowStyle]">

          <!-- 纵线渲染 -->
          <template v-if="num === 1 && hasXItems">
            <div
              v-for="(i) in (xItems.length - 1)"
              :key="i"
              :style="{
                left: `${i * mergeCellWidth}px`,
                height: `${rowsNum * yitemHeight}px`
              }"
              class="y-line"></div>
          </template>

          <template v-if="num === 1 && !hasYItems && self_list.default && self_list.default.length > 0">
            <time-cell
              v-for="(time, timeIndex) in self_list.default"
              :key="timeIndex + 'default'"
              :params="time"
              :per-time="perTime"
              :per-width="mergeCellWidth"
              :background-color="self_cellColors[0][timeIndex % self_cellColors[0].length]">
            </time-cell>
          </template>

          <template v-if="self_list[yItems[num - 1]] && self_list[yItems[num - 1]].length > 0">
            <time-cell
              v-for="(time, timeIndex) in self_list[yItems[num - 1]]"
              :key="timeIndex + yItems[num - 1]"
              :params="time"
              :per-time="perTime"
              :per-width="mergeCellWidth"
              :background-color="self_cellColors[num-1][timeIndex % self_cellColors[num-1].length]">
            </time-cell>
          </template>

        </div>
      </div>
    </div>

    <div
      v-if="hasControl"
      class="foot"
      :class="[hasYItems ? 'hasYItems' : '']">
      <time-view-slider
        :cell-width-range="[cellMinWidth, cellMinWidth + 100]"
        :cell-height-range="[cellMinHeight, cellMinHeight + 100]"
        :step-range="[step, 7]"
        @timeChange="sliderTimeChange"
        @heightChange="sliderHeightChange"
        />
    </div>
    
  
  </div>
</template>

<script>
import helper from './helper'
import TimeCell from './TimeCell'
import TimeViewSlider from './TimeViewSlider'

const DEFAULT_CELL_COLOR = ['#f5ffae', '#ffaeae'] // 默认元素颜色配置

// 时间视图组件
export default {
  name: 'TimeView',
  components: {
    TimeCell,
    TimeViewSlider
  },
  props: {
    totalTime: { // 横轴代表的总时间 --- 毫秒单位
      type: Number,
      default: 86400000 * 7 // 默认一周
    },
    step: { // 当前横轴时间粒度第几步 参考 helper.js
      type: Number,
      default: 0 // 默认一天
    },
    list: { // 传入的数据
      type: Array,
      default() {
        return []
      }
    },
    yAxis: { // y轴元素设置
      type: Object,
      default() {
        return {
          prop: 'priority', // 数据list中参考的keyName
          items: ['急迫', '优先', '普通', '缺省'], // y轴显示的文本
        }
      }
    },
    cellColors: { // 元素的颜色块
      type: Array,
      default() {
        return [ // yAxis.items有几个就传几个颜色数组
          ['#f5ffae', '#ffaeae'], // 颜色数组请最少传入一个颜色
          ['#f5ffae', '#ffaeae'],
          ['#f5ffae', '#ffaeae'],
          ['#f5ffae', '#ffaeae']
        ]
      }
    },
    limitTimes: { // 时间的一些限制
      type: Object,
      default() {
        return {
          startDate: '', // 允许的开始日期
          endDate: '', // 允许的结束日期
          week: ['1','2','3','4','5','6','7'], // 允许的星期
        }
      }
    },
    hasControl: { // 是否有滑块控制
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      yAxisCompelete: false,
      yItems: [],
      // yItems: [],
      xItems: [],
      perTime: 0,
      cellWidth: 100,
      cellHeight: 70,
      cellMinHeight: 0,
      cellMinWidth: 0,

      self_list: { // 最终此组件需要展示的数据格式
        default: []
      },
      self_step: 0,
    }
  },
  created() {
   
  },
  mounted() {
  
  },
  watch: {
    // 监听步骤
    step: {
      immediate: true,
      handler(v) {
        this.changeStep(v)
      }
    },

    // 监听x轴元素
    // 生成对应每格对应时间
    xItems: {
      immediate: true,
      handler(v) {
        this.perTime = helper.getPerTime(this.self_step)
      }
    },
    // 监听y轴配置生成
    // y轴元素｜self_list
    yAxis: {
      immediate: true,
      handler(v) {
        // 有y轴的完整配置
        if (v && v.prop && v.items && v.items.length > 0) {{
          this.yItems = v.items.slice()
          let _list = {}
          v.items.forEach(element => {
            _list[element] = []
          });
          this.self_list = _list
        }} else {
          // y轴配置不完整
          this.yItems = []
          this.self_list = {
            default: []
          }
        }
        this.yAxisCompelete = true
        // 完成y轴配置
        // 进入list解析组合
        this._listParse()
        
      }
    },
    list: {
      immediate: true,
      handler(v) {
        this._listParse()
      }
    },
    limitTimes: {
      immediate: true,
      handler(v) {
        console.log(v)
        this._listParse()
      }
    }
  },
  computed: {
    mergeCellWidth(){
      return this.cellWidth < this.cellMinWidth ? this.cellMinWidth : this.cellWidth
    },
    cellStyle() {
      const cellHeight = this.cellHeight < this.cellMinHeight ? this.cellMinHeight : this.cellHeight
      const cellWidth = this.cellWidth < this.cellMinWidth ? this.cellMinWidth : this.cellWidth
      return {
        width: cellWidth + 'px',
        height: cellHeight + 'px'
      }
    },
    rowStyle() {
      let {width: cellWidth, height: cellHeight} = this.cellStyle
      cellWidth = Number(cellWidth.replace('px', ''))
      cellHeight = Number(cellHeight.replace('px', ''))
      return {
        width: (cellWidth * this.xItems.length) + 'px',
        height: cellHeight + 'px'
      }
    },
    rowsNum() { // 行数 用于行的循环渲染
      return this.yItems.length > 0 ? this.yItems.length : 1 // 依据纵轴参数生成，若无则最小给1行
    },
    hasYItems() { // 是否有y轴元素
      return this.yItems.length > 0
    },
    hasXItems() { // 是否有x轴元素
      return this.xItems.length > 0
    },
    yitemHeight() { // y轴每格的高度
      let {height: cellHeight} = this.cellStyle
      return Number(cellHeight.replace('px', ''))
    },
    self_cellColors() { // 内部的元素颜色配置数组 依据传入的cellColors来生成
      const cellColors = this.cellColors
      if (this.hasYItems) { // 有yitems
        let _cellColors = cellColors.slice()
        const _cellColorsLength = _cellColors.length
        // eslint-disable-next-line
        if (_cellColorsLength < this.rowsNum) { // 如果所设置的颜色行数少于所展示的行数
          // 采取concat自身补全
          const concat_times = ~~(this.rowsNum / _cellColorsLength)
          for (let i = 0; i < concat_times; i++) {
            _cellColors = _cellColors.concat(_cellColors)
          }
          _cellColors = _cellColors.slice(0, this.rowsNum) 
        }
        return _cellColors
      } else { // 无yitems模式
        return cellColors.length > 0 && cellColors[0].length > 0
          ? [cellColors[0]] : [DEFAULT_CELL_COLOR]
      }
    }
  },
  methods: {

    // 滑块时间单位控制器回调
    sliderTimeChange({step, cellWidth}) {
      this.cellWidth = cellWidth
      console.log(step)
      this.changeStep(step)
    },
    // 滑块y高控制器回调
    sliderHeightChange(cellHeight) {
      this.cellHeight = cellHeight
      this.setLayout()
    },

    // 改变step
    changeStep(v) {
      this.self_step = v
      this.xItems = helper.getXItems(v, this.totalTime)
      this.setLayout()
      this._listParse()
    },

    // 获取table的宽高 返回 数组[宽, 高]
    getTableSize() {
      const table = this.$refs.table
      if (!table) return [0, 0]
      return [table.offsetWidth, table.offsetHeight]
    },
    // 用于重排一些宽高属性
    setLayout() {
      this.$nextTick(() => {
        const [tableWidth, tableHeight] = this.getTableSize()
        // 设置y轴元素最小高度
        this.cellMinHeight = this.hasYItems 
          ? (tableHeight / this.yItems.length) - 2 // chrome需要减去boder的宽度 
          : tableHeight - 8 // chrome上需要8个像素正好不会出现滚动条占满

        const xlength = this.xItems.length < 6 ?
          this.xItems.length : 6
        // 设置x轴元素最小宽度
        this.cellMinWidth = tableWidth
          ? !this.hasXItems
          ? this.tableWidth - 2
          : (tableWidth / xlength) - 2
          : 0
      })  
    },
    // 对传入数据进行解析
    _listParse() {
      if (!this.yAxisCompelete) return
      let _list = {}
      if (this.hasYItems) {
        // 依照设置的y轴prop先将数据进行分组
        const {prop} = this.yAxis
        this.yItems.forEach(item => {
          _list[item] = []
        })
        this.list.forEach(item => {
          _list[item[prop]].push({
            ...item
          })
        })
        // 遍历每组进行将要展示的数据生成
        this.yItems.forEach(item => {
          _list[item] = helper.getDisplayData(_list[item], {
            step: this.self_step,
            totalTime: this.totalTime
          }, {
            startDate: this.limitTimes.startDate,
            endDate: this.limitTimes.endDate,
            week: this.limitTimes.week
          })
        })
        this.self_list = _list
        console.log('转换后的数据----', _list)
      } else {
        _list.default = helper.getDisplayData([...this.list], {
          step: this.self_step,
          totalTime: this.totalTime
        }, {
          startDate: this.limitTimes.startDate,
          endDate: this.limitTimes.endDate,
          week: this.limitTimes.week
        })
        this.self_list = _list
        console.log('转换后的数据----', _list)
      }
      this.setLayout()
    }
  }

}
</script>

<style lang="scss" scoped>
.time-view {
  width: 100%;
  height: 100%;
  position: relative;

  

  $xaxis-height: 40px;
  $yaxis-width: 60px;
  $foot-height: 30px;
  $table-width: calc(100% - #{$yaxis-width});
  $table-height: calc(100% - #{$xaxis-height});
  $table-hasfoot-height: calc(100% - #{$xaxis-height + $foot-height});
  

  .top {
    &.hasYItems {
      padding-left: $yaxis-width;
    }

    .x-axis {
      height: $xaxis-height;
      overflow-x: scroll;
      &::-webkit-scrollbar {
        display: none;
      }
      scrollbar-width: none; /* Firefox 64 */
      
      white-space: nowrap;
      .table-cell {
        display: inline-block;
        height: $xaxis-height !important;
        line-height: $xaxis-height;
        text-align: center;
      }
    }
  }

  .main {
    width: 100%;
    height: $table-height;
    &.has-foot {
      height: $table-hasfoot-height;
    }

    .y-axis {
      display: inline-block;
      width: $yaxis-width;
      height: 100%;
      overflow-y: scroll;
      &::-webkit-scrollbar {
        display: none;
      }
      scrollbar-width: none; /* Firefox 64 */
      .y-item {
        text-align: center;
        width: $yaxis-width !important;
      }
    }

    .time-view-table {
      width: 100%;
      display: inline-block;
      

      border: 1px solid #000;
      overflow: scroll;
      scrollbar-width: thin;
      height: 100%;

      &.hasYItems {
        width: $table-width;
      }
      

      .table-row {
        position: relative;
        white-space: nowrap;
        .table-cell {
          display: inline-block;
        }
      }

      .table-row + .table-row {
        border-top: 1px dashed #000;
      }

      .y-line {
        position: absolute;
        top: 0;
        border-right: 1px dashed #000;
      }

    }
  }

  .foot {
    height: $foot-height;
    &.hasYItems {
      padding-left: $yaxis-width;
    }
  }
 

  
}
</style>